Mehr ggplot2!

Setup

# install.packages(c("ggimage", "here", "tidyverse", "ggtext", "glue", "patchwork", "ggrepel"))

library(ggimage)
library(here)
library(patchwork)
library(tidyverse)
library(ggtext)
library(glue)
library(ggrepel)

Datensatz

Downloade den Datensatz direkt von GitHub:

characters <- readRDS(url("https://github.com/nickhaf/PlotWorkshop/raw/refs/heads/main/data/characters.rds"))

## Optional: Abspeichern
saveRDS(characters, here::here("data", "characters.rds"))

  • “Psychometrische”, crowd-sourced ratings für TV-Charaktere.
  • Zwei (mehr oder weniger) gegensätzliche Eigenschaften, werden auf einer Skala von 0 - 100 bewertet.

Foto von Ilse Orsel auf Unsplash

Datensatz Download Manuell (optional)

Nur machen, wenn es auf der vorherigen Folie nicht geklappt hat!

Ladet die characters-Daten hier herunter, und legt sie ebenfalls in eurem data-Ordner ab. Lest sie dann in R ein:

characters <- readRDS(here::here("data", "characters.rds"))

Wiederholung

Wir schauen uns jetzt Persönlichkeitseigenschaften von Charakteren aus Friends und How I Met Your Mother an.

Plotte die Ratings für die ausgewählten Charactere char_prepped. Auf der x-Achse sollte die Frage top_trait zu sehen sein, auf der y-Achse das Rating. Styling machen wir später! Außerdem sollten der Name der Charactere (char_name) nache color und der Name der TV-Show (uni_name) nach shape unterscheidbar sein.

ggplot(
  data = char_prepped,
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point()

Skalen und Legenden

Scales in ggplot2 control the mapping from data to aesthetics. They take your data and turn it into something that you can see, like size, colour, position or shape. (ggplot2: Elegant Graphics for Data Analysis)

Jede Aesthetic im Plot ist mit genau einer Skala verbunden:

Implizite Definition

ggplot(
  data = char_prepped,
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point()

Wird intern zu:

ggplot(
  data = char_prepped,
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point() +
  scale_x_discrete() +
  scale_y_continuous() +
  scale_colour_discrete() +
  scale_shape_discrete()




  • top_trait ist eine diskrete Variable: scale_x_discrete()
  • avg_rating ist kontinuierlich: scale_y_continuous()
  • char_name und uni_name sind diskret: scale_colour_discrete() und scale_shape_discrete()

Das können wir uns zunutze machen, um manuell Scales zu definieren.

Ändern der Skalen-Defaults

ggplot(
  data = char_prepped,
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point() +
  scale_x_discrete(name = "Eigenschaft") +
  scale_y_continuous(name = "Mittleres Rating") +
  scale_colour_discrete(name = "Charakter") +
  scale_shape_discrete(name = "Serie")

Eigentlich würden wir dafür labs(x = "Eigenschaft", y = "Mittleres Rating", color = "Charakter", shape = "Serie") nutzen. Wir sehen so aber, dass Achsen- und Legendentitel jeweils Skalennamen sind.

Skalentypen

ggplot(
  data = char_prepped,
  mapping = aes(x = top_trait, y = avg_rating, colour = avg_rating, shape = uni_name)
) +
  geom_point() +
  scale_y_log10(name = "Mittleren Rating log") +
  scale_colour_continuous()

Hier haben wir jetzt eine log-transormierende und eine kontinuierliche Skala.

Eine Übersicht über die möglichen Skalentypen findet sich hier.

Anwendungsfälle: Farben/Formen

Oft macht es Sinn, die Farben direkt über einen named vector zu definieren. Dadurch bekommen alle Plots, die diese Variablen nutzen, auch sicher die gleichen Aesthetics zugeordnet. Dadurch wird jedem Element in der color-Variable genau die gewünschte Farbe zugeordnet:

char_colors <- c(
  "Ted Mosby" = "blue", "Robin Scherbatsky" = "red", "Barney Stinson" = "green", "Lily Aldrin" = "purple", "Marshall Eriksen" = "orange", "Rachel Green" = "pink", "Monica Geller" = "brown", "Phoebe Buffay" = "yellow", "Joey Tribbiani" = "cyan"
)

ggplot(
  data = char_prepped,
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point(size = 3) +
  scale_colour_manual(values = char_colors)

Anwendungsfälle: Farben/Formen

Genauso funktioniert das für Formen:

char_colors <- c(
  "Ted Mosby" = "blue", "Robin Scherbatsky" = "red", "Barney Stinson" = "green", "Lily Aldrin" = "purple", "Marshall Eriksen" = "orange", "Rachel Green" = "pink", "Monica Geller" = "brown", "Phoebe Buffay" = "yellow", "Joey Tribbiani" = "cyan"
)
char_shapes <- c("Friends" = 12, "How I Met Your Mother" = 18)

ggplot(
  data = char_prepped,
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point(size = 3) +
  scale_colour_manual(values = char_colors) +
  scale_shape_manual(values = char_shapes)

Anwendungsfälle: Skalen-Ticks

Versuche, die y-Achse so zu skalieren, dass sie von 0 bis 100 geht und in 10er Schritten skaliert ist. Nutze die interne R-Hilfe, aber verzichte auf Internet/KI.

ggplot(
  data = char_prepped,
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point()
ggplot(
  data = char_prepped,
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point() +
  scale_y_continuous(
    name = "Mittleres Rating",
    breaks = seq(0, 100, by = 10),
    limits = c(0, 100)
  )

Legenden

  • Legenden werden automatisch erzeugt.
  • Jede Skala bekommt eine Legende zugeordnet.
  • Sie nehmen die grafischen Eigenschaften (Aesthetics) und ordnen sie den Datenwerten zu. Man kann sie daher als die „Umkehrfunktion“ der jeweiligen Skalen verstehen.

Legenden und Achsen sind funktional äquivalent und werden in ggplot2 unter dem Begriff guides zusammengefasst.

Scale Guides

Jede Skala (und damit jede Aesthetic) bekommt einen Guide zugeordnet. Intern passiert das über guides(). Wir können guides() also nutzen, um die Legende zu stylen:

ggplot(
  data = char_prepped,
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point() +
  guides(color = guide_legend(
    title = "Charaktere",
    ncol = 2, ## Mehr Spalten in der Legende
    reverse = TRUE, ## Reihenfolge umkehren
    override.aes = list(size = 3)
  )) ## Größe der Punkte in der Legende ändern

Mögliche guide-Funktionen

  • guide_colourbar()
  • guide_coloursteps()
  • guide_axis()
  • guide_legend()
  • guide_bins()

Nutze das gerade gelernte und versuche, die x-Achsenbeschriftung um 90 Grad zu drehen, um sie lesbarer zu machen. Nutze die interne R-Hilfe, aber versuche, es ohne Internet/KI zu lösen:

ggplot(
  data = char_prepped,
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point()
ggplot(
  data = char_prepped,
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point() +
  guides(x = guide_axis(angle = 90))

Ich nutze außerdem die Spalte top_trait, damit die Achsenbeschriftung kürzer wird. Das sieht schon besser aus, aber wir haben ein Overplotting-Problem!

Text-Geoms

Foto von Natalia Y. auf Unsplash

geom_label{}

ggplot(
  data = char_prepped,
  mapping = aes(x = top_trait, y = avg_rating, shape = uni_name)
) +
  geom_label(aes(label = char_name))

geom_text() (mit ggrepel)

library(ggrepel)

ggplot(
  data = char_prepped,
  mapping = aes(x = bottom_trait, y = avg_rating, shape = uni_name)
) +
  geom_point() +
  geom_text_repel(aes(label = char_name))

ggtext

ggtext erlaubt es, Markdown und HTML-Code in ggplot2 zu nutzen.

library(ggtext)

char_prepped_2 <- char_prepped %>%
  mutate(char_name_label = case_when(
    char_name == "Monica Geller" & top_trait == "orderly" ~ "Monica ist sehr <span style='color:black'>ordentlich</span>",
    TRUE ~ NA
  ))

ggplot(
  data = char_prepped_2,
  mapping = aes(x = top_trait, y = avg_rating, shape = uni_name, label = char_name_label, color = char_name)
) +
  geom_point() +
  geom_richtext(
    nudge_x = 0.75, nudge_y = 1, fill = NA, label.color = NA, # remove background and outline
    label.padding = grid::unit(rep(0, 4), "pt")
  )

ggtext

char_prepped_3 <- char_prepped %>%
  mutate(char_name_bold = paste0("**", char_name, "**"))


ggplot(
  data = char_prepped_3,
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point() +
  facet_wrap(vars(char_name_bold)) +
  theme(
    strip.text = element_markdown()
  )

Adjustment: hjust/vjust vs. nudge_x/nudge_y

hjust

ggplot(
  data = char_prepped %>% filter(char_name == "Lily Aldrin"),
  mapping = aes(x = bottom_trait, y = avg_rating, shape = uni_name)
) +
  geom_point() +
  geom_text(aes(label = char_name), hjust = 0.5)

ggplot(
  data = char_prepped %>% filter(char_name == "Lily Aldrin"),
  mapping = aes(x = bottom_trait, y = avg_rating, shape = uni_name)
) +
  geom_point() +
  geom_text(aes(label = char_name), hjust = 0)

ggplot(
  data = char_prepped %>% filter(char_name == "Lily Aldrin"),
  mapping = aes(x = bottom_trait, y = avg_rating, shape = uni_name)
) +
  geom_point() +
  geom_text(aes(label = char_name), hjust = 1)

vjust

ggplot(
  data = char_prepped %>% filter(char_name == "Ted Mosby"),
  mapping = aes(x = bottom_trait, y = avg_rating, shape = uni_name)
) +
  geom_point() +
  geom_text(aes(label = char_name), vjust = 1)

ggplot(
  data = char_prepped %>% filter(char_name == "Ted Mosby"),
  mapping = aes(x = bottom_trait, y = avg_rating, shape = uni_name)
) +
  geom_point() +
  geom_text(aes(label = char_name), vjust = 0)

ggplot(
  data = char_prepped %>% filter(char_name == "Ted Mosby"),
  mapping = aes(x = bottom_trait, y = avg_rating, shape = uni_name)
) +
  geom_point() +
  geom_text(aes(label = char_name), vjust = -1)

Nudging

Nudging erfolgt auf der gleichen Skala wie die Werte.

Nudge um eine halbe Einheit nach rechts.

ggplot(
  data = char_prepped %>% filter(char_name == "Rachel Green"),
  mapping = aes(x = bottom_trait, y = avg_rating, shape = uni_name)
) +
  geom_point() +
  geom_text(aes(label = char_name), nudge_x = 0.5)

Nudge um 5 Einheiten nach unten.

ggplot(
  data = char_prepped %>% filter(char_name == "Rachel Green"),
  mapping = aes(x = bottom_trait, y = avg_rating, shape = uni_name)
) +
  geom_point() +
  geom_text(aes(label = char_name), nudge_y = -5)

Faceting



Aufteilen des Plots nach einer oder mehr Gruppen


Foto von Laura Cleffmann auf Unsplash

Faceting

Anordnen von einer einzelnen Variable in einem Raster:

facet_wrap(): Erstellt ein Band aus Kacheln

ggplot(
  data = char_prepped %>% filter(char_name %in% c("Robin Scherbatsky", "Monica Geller", "Barney Stinson", "Joey Tribbiani")), ## Subset wegen Platzproblemen
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point() +
  guides(x = guide_axis(angle = 90)) +
  facet_wrap(vars(char_name), nrow = 4)

facet_grid(): Erstellt ein Grid aus Kacheln

ggplot(
  data = char_prepped %>% filter(char_name %in% c("Robin Scherbatsky", "Monica Geller", "Barney Stinson", "Joey Tribbiani")),
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point() +
  guides(x = guide_axis(angle = 90)) +
  facet_grid(char_name ~ .)

Versuche nun, den Plot über zwei Dimensionen (char_name und uni_name) zu facetten, entweder mit facet_wrap() oder facet_grid().

ggplot(
  data = char_prepped %>% filter(char_name %in% c("Robin Scherbatsky", "Monica Geller", "Barney Stinson", "Joey Tribbiani")),
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point() +
  guides(x = guide_axis(angle = 90))

ggplot(
  data = char_prepped %>% filter(char_name %in% c("Robin Scherbatsky", "Monica Geller", "Barney Stinson", "Joey Tribbiani")),
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point() +
  guides(x = guide_axis(angle = 90)) +
  facet_wrap(vars(char_name, uni_name), nrow = 4)

ggplot(
  data = char_prepped %>% filter(char_name %in% c("Robin Scherbatsky", "Monica Geller", "Barney Stinson", "Joey Tribbiani")),
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point() +
  guides(x = guide_axis(angle = 90)) +
  facet_grid(char_name ~ uni_name)

Facetting - Mehrere Variablen

Anordnen von mehreren Variable in einem Raster:

ggplot(
  data = char_prepped %>% filter(char_name %in% c("Robin Scherbatsky", "Monica Geller", "Barney Stinson", "Joey Tribbiani")),
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point() +
  guides(x = guide_axis(angle = 90)) +
  facet_wrap(vars(char_name, uni_name), nrow = 4)

ggplot(
  data = char_prepped %>% filter(char_name %in% c("Robin Scherbatsky", "Monica Geller", "Barney Stinson", "Joey Tribbiani")),
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point() +
  guides(x = guide_axis(angle = 90)) +
  facet_grid(char_name ~ uni_name)

Facetting - Tipps

Plot alle Punkte

char_prepped_background <- char_prepped %>%
  mutate(char_name_bg = char_name) %>%
  select(-char_name)

ggplot(char_prepped, aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)) +
  # background lines: drawn in every facet, grouped by country_bg
  geom_jitter(
    data = char_prepped_background,
    aes(group = char_name_bg),
    color = "grey70",
    alpha = 0.7,
    size = 1,
    height = 0,
    width = 0.1
  ) +
  geom_point(size = 2) +
  guides(x = guide_axis(angle = 90)) +
  facet_wrap(vars(char_name)) +
  guides(color = "none") +
  theme_bw()

Facetting - Tipps

Plot Mittelwerte

dat_mean <- char_prepped %>%
  group_by(top_trait) %>%
  summarise(mean_rating = mean(avg_rating)) %>%
  ungroup()


ggplot(char_prepped, aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)) +
  geom_point(
    data = dat_mean,
    aes(x = top_trait, y = mean_rating),
    inherit.aes = FALSE,
    color = "grey70",
    size = 3,
    alpha = 0.7
  ) +
  geom_point() +
  facet_wrap(vars(char_name)) +
  guides(color = "none") +
  theme_bw()

Standardisierung könnte beim Vergleich zwischen den Fragen helfen - das kommt aber auf die finale Fragestellung an. Ist aber ein Punkt, den man zumindest im Hinterkopf behalten sollte.

Versuche nun, einen Lollipop-Plot aus diesem Plot zu machen.

dat_mean <- char_prepped %>%
  group_by(top_trait) %>%
  summarise(mean_rating = mean(avg_rating)) %>%
  ungroup()


ggplot(char_prepped, aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)) +
  geom_point(
    data = dat_mean,
    aes(x = top_trait, y = mean_rating),
    inherit.aes = FALSE,
    color = "grey70",
    size = 3,
    alpha = 0.7
  ) +
  geom_point() +
  facet_wrap(vars(char_name)) +
  guides(color = "none") +
  theme_bw()

dat_mean <- char_prepped %>%
  group_by(top_trait) %>%
  summarise(mean_rating = mean(avg_rating)) %>%
  ungroup()


ggplot(char_prepped, aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)) +
  geom_point(
    data = dat_mean,
    aes(x = top_trait, y = mean_rating),
    inherit.aes = FALSE,
    color = "grey70",
    size = 3,
    alpha = 0.7
  ) +
  geom_point() +
  facet_wrap(vars(char_name)) +
  guides(color = "none") +
  theme_bw() +
  geom_segment(
    aes(
      x = top_trait, xend = top_trait,
      y = 0, yend = avg_rating,
      group = interaction(char_name, uni_name)
    ),
    linewidth = 0.5,
    alpha = 0.5
  )

Sortieren

Sortieren, läuft in ggplot2 oft über factor().

char_prepped$uni_name <- factor(char_prepped$uni_name, levels = c("How I Met Your Mother", "Friends"))

Jetzt ist die Reihenfolge der Facetten umgekehrt:

ggplot(
  data = char_prepped,
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point() +
  facet_wrap(vars(uni_name), nrow = 4) +
  theme_bw()

Themes

Themes

  • Mit Themes kann man die nicht datenbezogenen Elemente eines Plots einstellen. Das ist z.B. plot.title oder axis.ticks.x.
  • Zu jedem Theme-Element gehört eine Element-Funktion: Oft brauchen wir z.B. element_text(), mit welchem wir z.B. den Titel stylen können: Farbe, Schriftart …
  • Es gibt bereits vorgefertigte Themes, man kann aber auch einzelne Element mit theme() überschreiben.

Themes: Vorgefertigt

ggplot(
  data = char_prepped,
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point() +
  facet_wrap(vars(uni_name), nrow = 4) +
  theme_dark()

Eine Übersicht über Standard-Themes findet ihr hier. Das Paket ggthemes bietet noch weitere Themes an.

Themes: Anpassen

ggplot(
  data = char_prepped,
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)
) +
  geom_point() +
  facet_wrap(vars(uni_name), nrow = 4) +
  theme_bw() +
  labs(
    title = "Charaktereigenschaften von TV-Charakteren",
    subtitle = "Friends vs. How I Met Your Mother"
  ) +
  theme(plot.title = element_text(color = "red"))

Style nun unseren Lollipop-Plot mit einem vorgefertigtem Theme deiner Wahl.

Passe danach folgendes an:

  • Setze die Hintergrundfarbe der Legende und des Plots auf “#06402B”. Dafür wird ein anderes element_ gebraucht. Findest du heraus welches?
  • Setze die Textfarbe im gesamten Plot auf weiß.
  • Versuche, die x-Achsen-Label innerhalb von themes() zu drehen. Wir hatten das vorhin schon einmal in guides() gemacht.
  • Optional: Ändere die Schriftart mit showtext.
dat_mean <- char_prepped %>%
  group_by(top_trait) %>%
  summarise(mean_rating = mean(avg_rating)) %>%
  ungroup()


ggplot(char_prepped, aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)) +
  geom_point(
    data = dat_mean,
    aes(x = top_trait, y = mean_rating),
    inherit.aes = FALSE,
    color = "grey70",
    size = 3,
    alpha = 0.7
  ) +
  geom_point() +
  facet_wrap(vars(char_name)) +
  guides(color = "none") +
  theme_bw() +
  geom_segment(
    aes(
      x = top_trait, xend = top_trait,
      y = 0, yend = avg_rating,
      group = interaction(char_name, uni_name)
    ),
    linewidth = 0.5,
    alpha = 0.5
  ) +
  labs(
    title = "Charaktereigenschaften von TV-Charakteren",
    subtitle = "Friends vs. How I Met Your Mother"
  )
library(showtext)
font_add_google("Playfair Display")


dat_mean <- char_prepped %>%
  group_by(top_trait) %>%
  summarise(mean_rating = mean(avg_rating)) %>%
  ungroup()


ggplot(char_prepped, aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name)) +
  geom_point(
    data = dat_mean,
    aes(x = top_trait, y = mean_rating),
    inherit.aes = FALSE,
    color = "grey70",
    size = 3,
    alpha = 0.7
  ) +
  geom_point() +
  facet_wrap(vars(char_name)) +
  guides(color = "none") +
  theme_bw() +
  geom_segment(
    aes(
      x = top_trait, xend = top_trait,
      y = 0, yend = avg_rating,
      group = interaction(char_name, uni_name)
    ),
    linewidth = 0.5,
    alpha = 0.5
  ) +
  labs(
    title = "Charaktereigenschaften von TV-Charakteren",
    subtitle = "Friends vs. How I Met Your Mother"
  ) +
  theme(
    legend.background = element_rect(fill = "#06402B"),
    plot.background = element_rect(fill = "#06402B"),
    text = element_text(color = "white", family = "Playfair Display"),
    axis.text = element_text(color = "white"),
    axis.text.x = element_text(angle = 90)
  )

Kordinatensysteme

Foto von Ujjwal Chettri auf Unsplash

Koordinatensysteme

Zwei Aufgaben:

  • Kombinieren der Positions-Aesthetics (Positions 1 & Position 2) zu einem 2d Raum.
    • Linear: x & y
    • Polar: Winkel und Radius
    • Karte: Breite und Länge
  • Zeichnen der Achsen und Rasterlinien

Typen

Linear

  • coord_cartesian(): Default
  • coord_flip: Tauscht x und y Achse
  • coord_fixed(): Fixes Seitenverhältnis.

Nicht-linear

  • coord_map: Kartenprojektion
  • coord_polar: Polar-Koordinaten (Kreise)
  • coord_trans: Transformation der Positionen

Polar-Koordinaten

ggplot(
  data = char_prepped,
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name, group = top_trait)
) +
  geom_point() +
  geom_segment(
    aes(
      x = top_trait, xend = top_trait,
      y = 0, yend = avg_rating,
      group = interaction(char_name, uni_name)
    ),
    linewidth = 0.5
  ) +
  ylim(0, 100) +
  facet_wrap(vars(char_name)) +
  coord_polar()

Kombinieren

Foto von Raúl Cacho Oses auf Unsplash

Patchwork

Ich erstelle mir hier zwei gesonderte Plots, einmal nur mit Robin Scherbatsky und einmal mit allen anderen Charakteren.

char_prepped_robin <- char_prepped %>%
  filter(char_name == "Robin Scherbatsky")


p_robin <- ggplot(
  data = char_prepped_robin,
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name, group = top_trait)
) +
  geom_point() +
  geom_segment(
    aes(
      x = top_trait, xend = top_trait,
      y = 0, yend = avg_rating,
      group = interaction(char_name, uni_name)
    ),
    linewidth = 0.5
  ) +
  ylim(0, 100) +
  facet_wrap(vars(char_name)) +
  coord_polar() +
  theme_minimal()

p_rest <- ggplot(
  data = char_prepped %>% filter(!char_name == "Robin Scherbatsky"),
  mapping = aes(x = top_trait, y = avg_rating, colour = char_name, shape = uni_name, group = top_trait)
) +
  geom_point() +
  geom_segment(
    aes(
      x = top_trait, xend = top_trait,
      y = 0, yend = avg_rating,
      group = interaction(char_name, uni_name)
    ),
    linewidth = 0.5
  ) +
  ylim(0, 100) +
  facet_wrap(vars(char_name)) +
  coord_polar() +
  theme_minimal()

Patchwork

Patchwork erlaubt es, Plots zu kombinieren.

library(patchwork)

p_robin +
  p_rest

Patchwork: Stylen

library(patchwork)

p_robin +
  p_rest +
  plot_layout(widths = c(1, 2))

Spider-Plot

Vorlage von Tanya Shapiro